home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 31
/
Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso
/
Aminet
/
dev
/
c
/
vbccppcsrc.lha
/
vbcc
/
vlink
/
targets.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-03-07
|
26KB
|
906 lines
/* $VER: vlink targets.c V0.6c (05.02.99)
*
* This file is part of vlink, a portable linker for multiple
* object formats.
* Copyright (c) 1997-99 Frank Wille
*
* vlink is freeware and part of the portable and retargetable ANSI C
* compiler vbcc, copyright (c) 1995-99 by Volker Barthelmann.
* vlink may be freely redistributed as long as no modifications are
* made and nothing is charged for it. Non-commercial usage is allowed
* without any restrictions.
* EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
* SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
*
*
* v0.6c (05.02.99) phx
* ctors/dtors sections always start with 0xffffffff to provide
* compatibility with most file formats (e.g. ELF).
* v0.6a (19.12.98) phx
* Support for little endian object file formats.
* readsection()/writesection() obey current endianess of linking
* process.
* make_priptr_objects() updates linker symbols during add_da-
* ta_section().
* v0.6 (24.10.98) phx
* find_lnksec() finds a LinkedSection by its name and/or type
* (needed for ELF small data support).
* New target elf32powerup, which supports the PPC coprocessor
* boards from Phase5.
* v0.5e (05.10.98) phx
* new_priptr(), add_priptrs(), make_priptr_objects(). Support for
* artificial sections and objects, containing longwords sorted by
* priority. These sections are automatically terminated by a NULL
* pointer entry. Currently only used by ados-target for constructor
* and destructor function pointer lists (__ctors, __dtors).
* v0.5c (08.07.98) phx
* art_objunit() creates an artificial ObjectUnit + LinkFile.
* v0.5 (27.06.98) phx
* addlnksymbol(), findlnksymbol() for target-specific linker
* symbol support.
* smalldata_section() returns a pointer to the first section,
* which is referenced base relative.
* v0.3 (17.04.98) phx
* addlocsymbol() allows multiple defintions of local
* symbols with the same name.
* addreloc() adds another relocation to a section.
* relocsize() determines size in bytes of a relocation type.
* addxref() requires the addend as additional argument.
* ar-support functions for library archives.
* v0.1 (27.02.98) phx
* First version that seems to link AmigaOS ADOS and EHF
* objects and libraries. Many common features, like linking
* sections together which have relative references, are
* still missing. Also, PowerPC-ELF32 support is about to come.
* v0.0 (05.08.97) phx
* File created.
*/
#define TARGETS_C
#include "vlink.h"
unsigned long findsecbase(struct GlobalVars *,char *);
struct Symbol *findsymbol(struct GlobalVars *,char *name);
struct Symbol *addsymbol(struct GlobalVars *,struct Section *,char *,
uint32,uint8,uint8,uint8,uint8,uint32);
void addlocsymbol(struct GlobalVars *,struct Section *,char *,uint32,
uint8,uint8,uint8,uint32);
void addglobsym(struct GlobalVars *,struct Symbol *);
struct Symbol *addlnksymbol(struct FFFuncs *,struct Section *,char *,
uint32,uint8,uint8,uint8,uint8,uint32);
struct Symbol *findlnksymbol(struct FFFuncs *,char *);
void addreloc(struct Section *,struct Section *,uint32,uint32,uint8,int32);
void addxref(struct GlobalVars *,struct Section *,char *,uint32,uint8,
uint8,int32);
int32 readsection(struct GlobalVars *,uint8 *,uint8);
void writesection(struct GlobalVars *,uint8 *,uint8,uint32);
uint8 relocsize(uint8);
struct Section *create_section(struct ObjectUnit *,char *,uint8 *,
unsigned long);
struct Section *find_sect_type(struct ObjectUnit *,uint8,uint8);
struct Section *find_sect_id(struct ObjectUnit *,uint32);
struct LinkedSection *find_lnksec(struct GlobalVars *,char *,uint8,
uint8,uint8);
struct LinkedSection *smalldata_section(struct GlobalVars *);
void add_objunit(struct GlobalVars *,struct ObjectUnit *,bool);
struct ObjectUnit *create_objunit(struct LinkFile *,char *);
struct ObjectUnit *art_objunit(char *,uint8 *,unsigned long,uint8);
void new_priptr(struct ObjectUnit *,char *,char *,int,char *,uint32);
void add_priptrs(struct GlobalVars *,struct ObjectUnit *);
void make_priptr_objects(struct GlobalVars *);
bool ar_init(struct ar_info *,char *,unsigned long,char *);
bool ar_extract(struct ar_info *);
static struct Section *getsecptr(struct list *,uint32);
static struct Section *add_data_section(struct GlobalVars *,
struct ObjectUnit *,char *,uint8 *,
unsigned long);
struct FFFuncs *fff[] = {
#ifdef ADOS
&fff_amigaos,
#endif
#ifdef EHF
&fff_ehf,
#endif
#ifdef ELF32_PPC_BE
&fff_elf32ppcbe,
#endif
#ifdef ELF32_POWERUP
&fff_elf32powerup,
#endif
NULL
};
const char *sym_type[] = { "undef","abs","reloc","common" };
const char *sym_info[] = { ""," object"," function"," section"," file" };
const char *sym_bind[] = { "","local ","global ","weak " };
unsigned long findsecbase(struct GlobalVars *gv,char *name)
/* scan the secbases list for a base address definition */
{
struct SecBase *sb = gv->secbases;
while (sb) {
if (!strcmp(name,sb->name))
return (sb->base);
sb = sb->next;
}
}
struct Symbol *findsymbol(struct GlobalVars *gv,char *name)
/* return pointer to Symbol, if present */
{
struct Symbol *sym = gv->symbols[elf_hash(name)%SYMHTABSIZE];
while (sym) {
if (!strcmp(name,sym->name))
return (sym); /* symbol found! */
sym = sym->glob_chain;
}
return (NULL);
}
struct Symbol *addsymbol(struct GlobalVars *gv,struct Section *s,char *name,
uint32 val,uint8 type,uint8 flags,uint8 info,
uint8 bind,uint32 size)
/* Define a new symbol. If defined twice in the same object unit, then */
/* return a pointer to its first definition. Defining the symbol twice */
/* globally, is only allowed in different object units of a library. */
{
struct Symbol *sym;
struct ObjectUnit *ou = s->obj;
struct Symbol **chain = &s->obj->objsyms[elf_hash(name)%OBJSYMHTABSIZE];
while (sym = *chain) {
if (!strcmp(name,sym->name))
return (sym); /* symbol already defined - don't define it twice */
/* The target-specific routines have to handle this case. */
chain = &sym->obj_chain;
}
*chain = sym = alloc(sizeof(struct Symbol));
sym->glob_chain = sym->obj_chain = NULL;
sym->name = name;
sym->value = val;
sym->relsect = s;
sym->type = type;
sym->flags = flags;
sym->info = info;
sym->bind = bind;
sym->size = size;
if (bind==SYMB_GLOBAL || bind==SYMB_WEAK)
addglobsym(gv,sym);
return (NULL); /* ok, new symbol was created */
}
void addlocsymbol(struct GlobalVars *gv,struct Section *s,char *name,
uint32 val,uint8 type,uint8 flags,uint8 info,uint32 size)
/* Define a new local symbol. Local symbols are allowed to be */
/* multiply defined. */
{
struct Symbol *sym;
struct Symbol **chain = &s->obj->objsyms[elf_hash(name)%OBJSYMHTABSIZE];
while (sym = *chain)
chain = &sym->obj_chain;
*chain = sym = alloc(sizeof(struct Symbol));
sym->glob_chain = sym->obj_chain = NULL;
sym->name = name;
sym->value = val;
sym->relsect = s;
sym->type = type;
sym->flags = flags;
sym->info = info;
sym->bind = SYMB_LOCAL;
sym->size = size;
}
void addglobsym(struct GlobalVars *gv,struct Symbol *newsym)
/* insert symbol into global symbol hash table */
{
struct Symbol **chain = &gv->symbols[elf_hash(newsym->name)%SYMHTABSIZE];
struct Symbol *sym;
struct ObjectUnit *newou = newsym->relsect->obj;
while (sym = *chain) {
if (!strcmp(newsym->name,sym->name)) {
if (sym->bind == SYMB_GLOBAL) {
/* symbol already defined with global binding */
if (newsym->bind==SYMB_GLOBAL && newou->lnkfile->type<ID_LIBBASE) {
if (newsym->type==SYM_COMMON && sym->type==SYM_COMMON) {
if (newsym->size > sym->size) {
/* replace by common symbol with